package com.itheima.em.data;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * @author MJJ
 * @version 1.0
 * @date 2023/12/2
 */
@SuppressWarnings("unchecked")
@Data
public class CircleArraySynchronized<T> {
    private final int maxSize;// 指定数组的最大容量
    private boolean isCircle = false;//是否为满环
    private Boolean isCircleMsg = false;//是否为满环消息标记（获取后手动重置）
    private int rear = 0; // 队列尾 | 满环时的队列头
    private final Object[] arr; // 用于存放数据，模拟队列

    final Object mutex;// 需要同步的对象锁

    public CircleArraySynchronized(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new Object[maxSize];
        mutex = this;
    }
    /**
     * 添加数据到环形队列
     *
     * @param t
     */
    public void addQueue(T t) {
        synchronized (mutex) {
            // 直接将数据加入
            arr[rear] = t;
            if ((rear + 1) == maxSize) {
                isCircle = true;//锁定后不动
                isCircleMsg = true;//通知已经存储一圈了
            }
            // 将rear 后移，这里必须考虑取模
            rear = (rear + 1) % maxSize;
        }
    }


    // 显示队列的所有数据
    public List<T> getQueueList() {
        synchronized (mutex) {
            // 遍历
            if (isEmpty()) {
                return new ArrayList<>();
            }
            List<T> list = new ArrayList<>();
            // 从front开始遍历，遍历有效个数的元素
            int start = isCircle ? rear : 0;
            int end = isCircle ? rear + maxSize : rear;
            for (int i = start; i < end; i++) {
                list.add((T) arr[i % maxSize]);
            }
            return list;
        }
    }

    /**
     * 查询 从 0下标 到 最新添加 下标位置的 最新所有数据，
     * @return
     */
    public List<T> getNewDataQueueList() {
        synchronized (mutex) {
            // 遍历
            if (isEmpty()) {
                return new ArrayList<>();
            }
            List<T> list = new ArrayList<>();
            // 从front开始遍历，遍历有效个数的元素
            int end = rear==0?maxSize:rear;
            for (int i = 0; i < end; i++) {
                list.add((T) arr[i]);
            }
            return list;
        }
    }

    public int size() {
        return isCircle ? maxSize : rear;
    }

    public boolean isEmpty() {
        return size() == 0;
    }

}
